/*
 * JCalendar.java
 *
 * Created on 7-Mar-2010.
 */

package org.calendar;


import javax.swing.JPanel;
import javax.swing.border.Border;
import javax.swing.UIManager;

import java.awt.Color;
import java.awt.Font;
import java.awt.BorderLayout;

import java.util.Calendar;
import java.util.Date;
import java.util.Locale;

import org.calendar.event.*;

/**
 * This class is a Swing Component for choosing a day.
 *
 * @author Julie Duvillier
 */

public class JCalendar
        extends JPanel {
    
    private DefaultCalendarModel model;
    private JDaySelector daySelector;
    private JMonthNavigator monthNavigator;


    /**
     * Constructs a default JCalendar that is initialised with a default
     * calendar and locale.
     */
    public JCalendar(){
        this( Calendar.getInstance() );
    }

    /**
     * Constructs a JCalendar  that is initialised with a <code>calendar</code>
     * and the default locale.
     * @param calendar the calendar to use
     */
    public JCalendar( Calendar calendar ){
        this(calendar, Locale.getDefault());
    }

    /**
     * Constructs a JCalendar that is initialised with <code>calendar</code>
     * and <code>locale</code>.
     * @param calendar the calendar to use
     * @param locale the locale to use
     */
    public JCalendar(Calendar calendar, Locale locale){
        this( new DefaultCalendarModel( calendar, locale ));
    }

    /**
     * Constructs a JCalendar that is initialised with the
     * given <code>model</code>.
     * @param model the model for the calendar.
     */
    public JCalendar(DefaultCalendarModel model){
       this.model = model;
       setLayout( new BorderLayout(2,2) );
       initComponents();
    }

    /** Initialise the panel components */
    private void initComponents(){
        monthNavigator = new JMonthNavigator( model );
        daySelector =  new  JDaySelector( model );
        add(monthNavigator, BorderLayout.NORTH);
        add( daySelector );
       
    }

    /**
     * Add calendar listener.
     * The listener will receive events each time
     * the calendar selected date changes.
     * @param listener The calendar listener to add
     */
    public void addCalendarListener(CalendarListener listener){
        daySelector.addCalendarListeners(listener);
    }

    /**
     * Remove a calendar Listener.
     * @param listener The calendar listener to remove
     */
    public void removeCalendarListener(CalendarListener listener){
         daySelector.removeListeners(listener);
    }


    /**
     * Gets the model.
     * @return  The DefaultCalendarModel used by the calendar
     */
    public DefaultCalendarModel getModel(){
        return model;
    }

    /**
     * Gets the selected calendar with the selected
     * year,month,date.
     * It is an alternative to <code> getSelectedDate</code> method
     * @return a copy of the selected calendar
     */
    public Calendar getSelectedCalendar(){
        return daySelector.getSelectedCalendar();
    }

    /**
     * Gets the selected date as a <code>Date</code> object.
     * @return  value of the <code>Date</code> object.
     */
    public Date getSelectedDate(){
        return daySelector.getSelectedCalendar().getTime();
    }

    /**
     * Gets the locale
     * @return the locale value
     */
    @Override
    public Locale getLocale(){
        return model.getLocale();
    }

    /**
     * Sets the calendar to display without changing
     * the selected date.
     * @param calendar the new calendar to display
     */
    public void setCalendarToDisplay(Calendar calendar){
        model.setCalendarToDisplay(calendar);
    }

    /**
     * Sets the date to display without changing
     * the selected date.
     * @param date the new date to display
     */
    public void setDate(Date date){
        Calendar cal = (Calendar)model.getCalendarToDisplay().clone();
        cal.setTime(date);
        model.setCalendarToDisplay(cal);
    }

    /**
     * Sets the locale.
     * @param locale the value of the new locale
     */
    @Override
    public void setLocale(Locale locale){
        super.setLocale(locale);
        model.setLocale(locale);
    }

    /**
     * Sets the selected date
     *
     * @param date the value of the selected date
     */
    public void setSelectedDate(Date date){
        daySelector.setSelectedDate(date);
    }



    /*                  DECORATION ACCESSORS AND MUTATORS                     */

    /**
     * Gets the foreground colour of navigator's buttons.
     * @return navigator buttons' foreground <code>color</code>;
     */
    public Color getNavigButtonForeground(){
       return  monthNavigator.getButtonForeground();
    }

    /**
     * Gets the font of navigator's buttons.
     * @return navigator's buttons font.
     */
    public Font getNavigButtonFont(){
        return  monthNavigator.getButtonFont();
    }

    /**
     * Gets the background colour of the day of the week.
     * @return the day of the week background colour.
     */
    public Color getDayOfWeekBackground(){
        return daySelector.getDayLabelBackground();
    }

    /**
     * Gets the foreground colour of the day of the week.
     * @return the day labels foreground colour.
     */
    public Color getDayDayOfWeekForeground(){
        return daySelector.getDaylabelForeground();
    }

    /**
     * Gets the font of the day of the week.
     * @return the day of the week font.
     */
    public Font getDayDayOfWeekFont(){
        return daySelector.getDayLabelFont();
    }

    /**
     * Returns the border of the day of the week.
     * @return the border object for the day of the week.
     */
    public Border getDayDayOfWeekBorder(){
        return daySelector.getDayLabelBorder();
    }

    /**
     * Gets the font of days button.
     * @return days buttons font.
     */
    public Font getDayButtonFont(){
        return daySelector.getButtonFont();
    }

    /**
     * Gets the font of today button.
     * @return today button font.
     */
    public Font getTodayButtonFont() {
        return daySelector.getTodayButtonFont();
    }

    /**
     * Gets the foreground colour of the day buttons that are
     * not current month.
     * @return the foreground colour of the day buttons that are
     *          not current month.
     */
    public Color getOtherMonthButtonForeground() {
       return daySelector.getOtherMonthButtonForeground();
    }

    /**
     * Gets the foreground colour of the day buttons that are
     * current month.
     * @return the foreground colour of the day buttons that are
     *         current month.
     */
    public Color getCurrentMonthButtonForeground() {
        return daySelector.getOtherMonthButtonForeground();
    }

    /**
     * Sets the background colour of this component.
     * @param color the colour to become this component's colour.
     *
     */
    @Override
    public void setBackground( Color color){
        super.setBackground(color);
        if( daySelector != null ) {
            setDaySelectorBackground(color);
        }
        if ( monthNavigator != null ) {
            setMonthNavigatorBackground(color);
        }
        
    }

    /**
     * Set the month navigator background.
     * @param color the desired background colour.
     */
    public void setMonthNavigatorBackground( Color color){
        monthNavigator.setBackground(color);
    }

    /**
     * Sets the foreground colour of navigator's buttons.
     * @param color the colour to become the navigator's buttons foreground colour.
     */
    public  void setNavigButtonForeground(Color color){
         monthNavigator.setButtonForeground(color);
    }

    /**
     * Sets the font of navigator's buttons.
     * @param font the font to become navigator's buttons font
     */
    public  void setNavigButtonFont(Font font){
        monthNavigator.setButtonFont(font);
    }

    /**
     * Sets the contentAreaFilled property of navigator's button.
     * If <code>true</code> buttons will paint the content area. 
     * <p>
     * The default value is  <code>false </code> - so the content is not filled -
     * and become <code>true</code> on mouse over  - so the content is filled .
     * Setting the property to <code>true</code> will  reverse this.
     * @param b  if true, the content should be filled
     *              and become not  filled on mouse over;
     *           if false, the content area is not filled
     *              and become filled on mouse over
     */
     public  void setNavigButtonAreaFilled(boolean b){
       monthNavigator.setButtonAreaFilled(b);
    }

    /**
     * Sets the background colour of the day chooser.
     * @param color the colour to become the background colour.
     */
    public void setDaySelectorBackground( Color color){
        daySelector.setBackground(color);
    }
    
    
    /**
     * Sets the background colour of the day labels.
     * @param color the colour to become the background colour.
     */
    public void setDayLabelBackground( Color color ) {
        daySelector.setDayLabelForeground(color);
    }

    /**
     * Sets the foreground colour of the day labels.
     * @param color the colour to become the foreground colour.
     */
    public void setDayLabelForeground( Color color ) {
        daySelector.setDayLabelBackground(color);
    }

    /**
     * Sets the font of day labels.
     * @param font the font to become day labels' font
     */
    public void setDayLabelFont( Font font ){
        daySelector.setDayLabelFont(font);
    }

    /**
     * Sets the border of day labels.
     * @param border  the border to be rendered for day labels
     */
    public void setDayLabelBorder( Border border ) {
        daySelector.setDayLabelBorder(border);
    }


    /**
     * Sets the font of days buttons.
     * @param font  the font to become day buttons' font
     */
    public void setDayButtonFont( Font font ){
        daySelector.setButtonFont(font);
    }

    /**
     * Sets the font of today button.
     * @param font the font to become today buttons' font
     */
    public void setTodayButtonFont( Font font) {
        daySelector.setTodayButtonFont(font);
    }

    /**
     * Sets the the foreground color of day buttons that are
     * not current month.
     * @param color the color to become the foreground color.
     */
    public void setOtherMonthButtonForeground( Color color ){
        daySelector.setOtherMonthButtonForeground(color);
    }

    /**
     * Sets the the foreground color of day buttons that are
     * current month.
     * @param color the color to become the foreground color.
     */
    public void setCurrentMonthButtonForeground( Color color ){
        daySelector.setCurrentMonthButtonForeground(color );
    }

    /**
     * Sets the contentAreaFilled property of day buttons.
     * If <code>true</code> buttons will paint the content area.
     * <p>
     * The default value is  <code>false </code> and become <code>true</code>
     * on mouse over, So the content is filled on mouse over.
     * <p>
     * The selected button contentAreaFilled property take the opposite
     * value, so if the contentAreaFilled property is <code>true</code>
     * the contentAreaFilled property of tehs elected button will be
     * <code>false</code>.
     * <p>
     * Setting the property to <code>true</code> will reverse this.
     * @param b  if true, the content should be filled
     *              and become not  filled on mouse over;
     *           if false the content area is not filled
     *              and become filled on mouse over
     */
    public void setDayButtonContentAreaFilled(Boolean b){
        daySelector.setButtonAreaFilled(b);
    }

    
    public static void main(String[] args) {
        try{
           // UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
            UIManager.setLookAndFeel("com.sun.java.swing.plaf.windows.WindowsLookAndFeel");
            System.out.println(UIManager.getLookAndFeel().toString());
        }catch(Exception x){
                System.err.format("Error: %s%n", x);
        }
        javax.swing.JFrame frame = new javax.swing.JFrame();
        frame.getContentPane().add( new JCalendar() );
        frame.pack();
        frame.setDefaultCloseOperation(javax.swing.JFrame.EXIT_ON_CLOSE);
        frame.setVisible(true);

     }

}
